#ifndef SL_LOGGER_HPP
#define SL_LOGGER_HPP

// std Header
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

namespace sl
{
	class LogType
	{
	public:
		enum Type
		{
			None = 0,
			Info,
			Warning,
			Error,

			Count
		};

		static std::string ToString(LogType::Type type);

	private:
		static std::string myTypes[Type::Count];
	};

	class Logger;
	class FileLogger;

	class Log
	{
	public:
		Log();
		Log(LogType::Type type);
		virtual ~Log();

	protected:
		LogType::Type myLogType;

	public:
		virtual Log* Open(const std::string& filename = "");
		virtual Log* Close();
		virtual Log* Write(const std::string& text);
		virtual Log* Write(LogType::Type type, const std::string& text);

		/*Log operator<<(LogType::Type type);
		Log operator+(LogType::Type type);*/

		Log* SetLogType(LogType::Type type);
		/*virtual std::ostream& operator()();

	public:
		template <class O> std::ostream& operator<<(O& obj);
		template <class O> std::ostream& operator+(O& obj);*/
	};

	/*template <class O>
	std::ostream& Log::operator<<(O& obj)
	{
		//return *dynamic_cast<std::ostream*>(&(myStream << obj));
		return myStream << obj;
		//return std::cout << obj;
	}

	template <class O>
	std::ostream& Log::operator+(O& obj)
	{
		return log << obj;
	}*/

	class Logger : public Log
	{
	public:
		Logger();
		virtual ~Logger();

	protected:
		std::ostream& myStream;

	public:
		virtual Logger* Open(const std::string& filename = "");
		virtual Logger* Close();
		virtual Logger* Write(const std::string& text);
		virtual Logger* Write(LogType::Type type, const std::string& text);

	public:
		std::ostream& operator()();
	};

	class FileLogger : public Log
	{
	public:
		FileLogger(const std::string& filename = "");
		virtual ~FileLogger();

	protected:
		std::ofstream myStream;

	public:
		virtual FileLogger* Open(const std::string& filename = "");
		virtual FileLogger* Close();
		virtual FileLogger* Write(const std::string& text);
		virtual FileLogger* Write(LogType::Type type, const std::string& text);

	public:
		std::ofstream& operator()();
	};

	FileLogger* NewFileLogger(const std::string& filename);
}

#endif //SL_LOGGER_HPP